<?php

/**
 * 
 * Enter description here ...
 * @category 	GepardCore
 * @author 		taras
 * @package 	gDbo
 * @copyright 	Copyright (c) Taras Kudla, 2010
 *
 */
class gDboQuery
{
	const quoteValue = "'";
	const quoteCollumn = ':';
	
	const FETCH_ALL = 1;
	const FETCH_ONE = 2;
	const FETCH_LIST = 3;
	const FETCH_ASSOC = 4;
	const FETCH_ROW = 5;
	const FETCH_OBJECT = 6;
	
	/**
	 * 
	 * Enter description here ...
	 * @var gDbo
	 */
	private $db = null;
	
	private $sql = null;
	
	private $flagWasWhere = false;
	private $flagWasHaving = false;
	private $orWhere = false;
	private $andWhere = false;
	
	function __construct($db = null)
	{
		$this->db = $db;
	}
	
	/**
	 * 
	 * @return gDboQuery
	 */
	public function select()
	{
		$this->sql = 'SELECT ';
		return $this;
	}
	
	function __call($name,$args)
	{
		if( !empty($name) && preg_match('/^\_([A-z0-9_]+)/is',$name,$tmp)){
			$this->sql .= $tmp[1];
			return $this;
		}
	}
	
	public function escape($value)
	{
		return str_replace(self::quoteValue, '\\'.self::quoteValue, $value);
	}
	
	
	/**
	 * 
	 * Enter description here ...
	 * @param string $tables
	 * @param string $fields
	 * @return gDboQuery
	 */
	public function from($tables,$fields="*")
	{
		if( is_array($fields))
		{
			$tmpfields = null;
			$i=0;
			foreach ( $fields as $name=>&$value)
			{
				$tmpfields .= ($i!=0 ? ',' : '').(is_string($name) ? $this->escape($name) . ' AS ' . $value : $value);
				$i++;
			}
			$fields = $tmpfields;
		}
		$this->sql .= ' ' . $fields . ' FROM ';
		if( is_array($tables) )
		{
			$tmptables = null;
			foreach ($tables as $name=>&$value)
			{
				$tmptables .= is_string($name) ? $this->escape($name) . ' AS ' . $value : $value;
			}
			$fields = $tmpfields;
		}
		$this->sql .= ' '.$tables.' ';
		return $this;
	}
	/**
	 * 
	 * Enter description here ...
	 * @param string $sql
	 * @param array $values
	 * @return gDboQuery
	 */
	public function where($sql)
	{
		if( func_num_args()>1)
		{
			$values = array_slice(func_get_args(),1);
			if( is_array($values))
			{
				foreach ($values as $key=>&$value)
				{
					$sql = preg_replace('/\?/',is_string($value)?self::quoteValue.$this->escape($value).self::quoteValue:$value,$sql,1);
				}
			} 
			else
			{
				$sql = preg_replace('/\?/',is_string($values)?self::quoteValue.$this->escape($values).self::quoteValue:$values,$sql,1);
			}
		}
		$this->sql .= !$this->flagWasWhere ? ' WHERE ' . $sql : ($this->orWhere ? ' OR ' : $this->andWhere ? ' AND ' : ' ') . $sql;
		$this->flagWasWhere = true;
		$this->orWhere = false;
		$this->andWhere = false;
		return $this;
	}
	
	public function orWhere()
	{
		$params = func_get_args();
		$this->orWhere = true;
		return call_user_func_array(array($this,'where'), $params);
	}
	
	public function andWhere()
	{
		$params = func_get_args();
		$this->andWhere = true;
		return call_user_func_array(array($this,'where'), $params);
	}
	
	/**
	 * 
	 * Enter description here ...
	 * @param string $field
	 * @return gDboQuery
	 */
	public function order($field)
	{
		$this->sql .= ' ORDER BY '.$this->escape($field);
		return $this;
	}
	/**
	 * 
	 * Enter description here ...
	 * @param string $sql
	 * @param array $values
	 * @return gDboQuery
	 */
	public function having($sql,$values)
	{
		if( $values != null )
		{
			if( is_array($values))
			{
				foreach ($values as $key=>&$value)
				{
					$sql = preg_replace('/\?/',$this->escape($value),$sql);
				}
			} 
			else 
			{
				$sql = preg_replace('/\?/',$this->escape($values),$sql);
			}			
		}
		$this->sql .= !$this->flagWasHaving ? ' HAVING ' . $sql : ' ' . $sql;
		$this->flagWasHaving = true;
		return $this;		
	}
	/**
	 * 
	 * Enter description here ...
	 * @param string $sql
	 * @return gDboQuery
	 */
	public function group($sql)
	{
		$this->sql .= ' GROUP BY ' . $sql;
		return $this;
	}
	
	
	
	/**
	 * 
	 * Enter description here ...
	 * @return gDboQuery
	 */
	public function desc()
	{
		$this->sql .= ' desc';
		return $this;
	}
	
	/**
	 * 
	 * Enter description here ...
	 * @return gDboQuery
	 */	
	public function asc()
	{
		$this->sql .= ' asc';
		return $this;
	}
	
	/**
	 * 
	 * Enter description here ...
	 * @param integer $count
	 * @param integer $offset
	 * @return gDbormQuery
	 */
	public function limit($count,$offset = 0)
	{
		$this->sql .= ' LIMIT ' . $count . ' OFFSET '.$offset;
		return $this;
	}
	
	
	/*
	 * Update
	 */
	public function update()
	{
		$this->sql .= ' UPDATE ';
		return $this;
	}
	public function delete()
	{
		$this->sql .= ' DELETE ';
		return $this;
	}

	public function insert()
	{
		
	}
	
	
	
	
	/*
	 * Service
	 */
	public function clear()
	{
		$this->sql = null;
	}
	
	public function exec()
	{
		
	}
		
	/*
	 * Results
	 */
	public function fetchAll()
	{
		return $this->db->execute($this->sql,self::FETCH_ALL);
	}
	
	public function fetchOne()
	{
		return $this->db->execute($this->sql,self::FETCH_ONE);
	}
	
	public function fetchList()
	{
		return $this->db->execute($this->sql,self::FETCH_LIST);
	}
	
	public function fetchAssoc()
	{
		return $this->db->execute($this->sql,self::FETCH_ASSOC);	
	}
	
	public function fetchRow()
	{
		return $this->db->execute($this->sql,self::FETCH_ROW);	
	}
	
	public function fetchObject()
	{
		return $this->db->execute($this->sql,self::FETCH_OBJECT);
	}
	
	
	public function __toString()
	{
		return $this->sql;
	}
	
	public function toString()
	{
		return $this->sql;
	}
}